import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import random


class PropertyInsuranceCostAnalyzer:
    def __init__(self):
        # 初始化数据存储
        self.policy_data = None  # 保单数据
        self.reinsurance_data = None  # 再保业务数据
        self.expense_data = None  # 费用数据
        self.reserve_data = None  # 准备金数据
        self.tax_data = None  # 税金数据

    def generate_sample_data(self, start_date="2023-01-01", end_date="2024-12-31", n=1000):
        """生成样本数据，模拟业务场景中的各项数据"""
        # 生成日期范围
        date_range = pd.date_range(start=start_date, end=end_date, freq='D')

        # 1. 保单数据
        self.policy_data = pd.DataFrame({
            "policy_id": [f"POL{str(i).zfill(6)}" for i in range(n)],
            "business_type": np.random.choice(["财险", "人身险", "再保财险", "再保人身险"], n),
            "issue_date": np.random.choice(date_range, n),
            "original_premium": np.random.uniform(1000, 100000, n).round(2),  # 原保费收入
            "written_premium": np.random.uniform(500, 80000, n).round(2)  # 分保费收入
        })

        # 2. 再保分出业务数据
        self.reinsurance_data = pd.DataFrame({
            "reins_id": [f"RE{str(i).zfill(6)}" for i in range(n)],
            "policy_id": np.random.choice(self.policy_data["policy_id"], n),
            "ceded_premium": np.random.uniform(100, 20000, n).round(2),  # 分出保费
            "recovered_reinsurance_expense": np.random.uniform(50, 10000, n).round(2)  # 摊回分保费用
        })

        # 3. 费用数据
        self.expense_data = pd.DataFrame({
            "expense_id": [f"EXP{str(i).zfill(6)}" for i in range(n)],
            "policy_id": np.random.choice(self.policy_data["policy_id"], n),
            "business_management_fee": np.random.uniform(100, 5000, n).round(2),  # 业务及管理费
            "commission": np.random.uniform(50, 3000, n).round(2),  # 手续费及佣金
            "reinsurance_fee": np.random.uniform(30, 2000, n).round(2)  # 分保费用
        })

        # 4. 准备金数据
        self.reserve_data = pd.DataFrame({
            "reserve_id": [f"RES{str(i).zfill(6)}" for i in range(n)],
            "policy_id": np.random.choice(self.policy_data["policy_id"], n),
            "claim_payment": np.random.uniform(500, 50000, n).round(2),  # 赔付支出
            "unearned_premium_reserve_extracted": np.random.uniform(200, 10000, n).round(2),  # 提取未到期责任准备金
            "unearned_premium_reserve_returned": np.random.uniform(100, 8000, n).round(2),  # 转回未到期责任准备金
            "outstanding_claims_reserve_extracted": np.random.uniform(300, 15000, n).round(2),  # 提取未决赔款准备金
            "outstanding_claims_reserve_returned": np.random.uniform(150, 12000, n).round(2)  # 转回未决赔款准备金
        })

        # 5. 税金数据
        self.tax_data = pd.DataFrame({
            "tax_id": [f"TAX{str(i).zfill(6)}" for i in range(n)],
            "policy_id": np.random.choice(self.policy_data["policy_id"], n),
            "business_tax_surcharge": np.random.uniform(50, 5000, n).round(2)  # 保险业务营业税金及附加
        })

        print("样本数据生成完成")
        return self

    def calculate_earned_premium(self, policy_row, reinsurance_row, reserve_row):
        """计算已赚保费"""
        return (policy_row["original_premium"] - reinsurance_row["ceded_premium"] -
                reserve_row["unearned_premium_reserve_extracted"] +
                reserve_row["unearned_premium_reserve_returned"])

    def calculate_indicators(self):
        """计算各项成本费用指标"""
        # 合并所有数据
        merged_data = self.policy_data.merge(self.reinsurance_data, on="policy_id", how="left")
        merged_data = merged_data.merge(self.expense_data, on="policy_id", how="left")
        merged_data = merged_data.merge(self.reserve_data, on="policy_id", how="left")
        merged_data = merged_data.merge(self.tax_data, on="policy_id", how="left")

        # 计算已赚保费
        merged_data["earned_premium"] = merged_data.apply(
            lambda row: self.calculate_earned_premium(row, row, row), axis=1
        )

        # 1. 赔付率
        merged_data["loss_ratio"] = (
                (merged_data["claim_payment"] + merged_data["outstanding_claims_reserve_extracted"] -
                 merged_data["outstanding_claims_reserve_returned"]) / merged_data["earned_premium"] * 100
        ).round(2)

        # 2. 综合费用率
        merged_data["comprehensive_expense_ratio"] = (
                (merged_data["business_management_fee"] + merged_data["commission"] +
                 merged_data["reinsurance_fee"] + merged_data["business_tax_surcharge"] -
                 merged_data["recovered_reinsurance_expense"]) / merged_data["earned_premium"] * 100
        ).round(2)

        # 3. 综合成本率
        merged_data["comprehensive_cost_ratio"] = (
                (merged_data["claim_payment"] + merged_data["outstanding_claims_reserve_extracted"] -
                 merged_data["outstanding_claims_reserve_returned"] + merged_data["business_management_fee"] +
                 merged_data["commission"] + merged_data["reinsurance_fee"] +
                 merged_data["business_tax_surcharge"] - merged_data["recovered_reinsurance_expense"]) /
                merged_data["earned_premium"] * 100
        ).round(2)

        # 4. 保费费用率
        merged_data["premium_expense_ratio"] = (
                merged_data["business_management_fee"] / merged_data["original_premium"] * 100
        ).round(2)

        # 5. 手续费及佣金比率
        merged_data["commission_ratio"] = (
                merged_data["commission"] / merged_data["original_premium"] * 100
        ).round(2)

        # 6. 分保费用比率
        merged_data["reinsurance_fee_ratio"] = (
                merged_data["reinsurance_fee"] / merged_data["written_premium"] * 100
        ).round(2)

        return merged_data

    def statistical_analysis(self, data, period="month"):
        """
        按周期进行统计分析
        period: week(七日), month(月), year(年)
        工单编号：大数据-八维保险数据挖掘-04-财产保险成本费用相关
        """
        # 确保日期列格式正确
        data["issue_date"] = pd.to_datetime(data["issue_date"])

        # 设置日期为索引
        data = data.set_index("issue_date")

        # 选择需要统计的数值列
        numeric_cols = ["loss_ratio", "comprehensive_expense_ratio", "comprehensive_cost_ratio",
                        "premium_expense_ratio", "commission_ratio", "reinsurance_fee_ratio"]

        # 按不同周期分组统计（修正：移除numeric_only参数，改用列选择方式）
        if period == "week":
            grouped = data[numeric_cols].resample('7D').mean()
            grouped.index = grouped.index.strftime('%Y-%m-%d')
            period_name = "七日周期"
        elif period == "month":
            grouped = data[numeric_cols].resample('M').mean()
            grouped.index = grouped.index.strftime('%Y-%m')
            period_name = "月度"
        elif period == "year":
            grouped = data[numeric_cols].resample('Y').mean()
            grouped.index = grouped.index.strftime('%Y')
            period_name = "年度"
        else:
            raise ValueError("周期参数错误，可选值：week, month, year")

        print(f"\n{period_name}指标统计（平均值）：")
        print(grouped)

        return grouped


if __name__ == "__main__":
    # 初始化分析器
    analyzer = PropertyInsuranceCostAnalyzer()

    # 生成样本数据
    analyzer.generate_sample_data()

    # 计算指标
    indicators_data = analyzer.calculate_indicators()

    # 按不同周期统计
    analyzer.statistical_analysis(indicators_data, period="week")  # 七日统计
    print("----------------------------------------------------")
    analyzer.statistical_analysis(indicators_data, period="month")  # 月度统计
    print("----------------------------------------------------")
    analyzer.statistical_analysis(indicators_data, period="year")  # 年度统计